/**
 * @file TcpConnection.cc
 * @author zziywang (zziywang@163.com)
 * @brief { life is too short to learn cpp! }
 * @version 1.0
 * @date 2022-05-07
 *
 * @copyright Copyright (c) 2022
 *
 */

#include "TcpConnection.hh"
#include <sstream>
using std::ostringstream;

namespace snow
{

TcpConnection::TcpConnection(int fd)
    : sock_(fd),
      sockio_(fd),
      localAddr_(getLocalAddress()),
      peerAddr_(getPeerAddress()),
      isShutdownWrite_(false) {}

TcpConnection::~TcpConnection()
{
    if (!isShutdownWrite_) {
        shutdown();
    }
}

void TcpConnection::shutdown()
{
    if (!isShutdownWrite_) {
        isShutdownWrite_ = true;
        sock_.shutdownWrite();
    }
}

string TcpConnection::recv()
{
    char buf[65535] = {0};
    sockio_.readn(buf, sizeof(buf));
    return string(buf);
}

string TcpConnection::recvLine()
{
    char buf[65535] = {0};
    sockio_.readLine(buf, sizeof(buf));
    return string(buf);
}
void TcpConnection::send(const string &msg)
{
    sockio_.writen(msg.c_str(), msg.size());
}

// 打印TCP连接，四元组（本端ip,port,对端ip,port)
string TcpConnection::printTcp() const
{
    ostringstream oss;
    oss << localAddr_.getIp() << ":" << localAddr_.getPort()
        << " --> " << peerAddr_.getIp() << ":" << peerAddr_.getPort();
    return oss.str();
}

InetAddress TcpConnection::getLocalAddress() const
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr);
    if (-1 == ::getsockname(sock_.getFd(), (struct sockaddr *)&addr, &len)) {
        perror("getsockname");
    }
    return InetAddress(addr);
}

InetAddress TcpConnection::getPeerAddress() const
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr);
    if (-1 == ::getpeername(sock_.getFd(), (struct sockaddr *)&addr, &len)) {
        perror("getpeername");
    }
    return InetAddress(addr);
}

} // namespace snow